package cn.juque.common.filters;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.juque.common.abstracts.AbstractRequestDTO;
import cn.juque.common.utils.ValidatorUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

import java.util.Objects;

/**
 * @author juque
 * @version 1.0.0
 * <ul>
 *     <li>检验参数</li>
 * </ul>
 * @date 2024-03-13
 **/
@Slf4j
@Activate(group = {CommonConstants.PROVIDER, CommonConstants.CONSUMER}, order = 2)
public class CheckArgumentFilter implements Filter {

    private ValidatorUtil validatorUtil;

    /**
     * Always call invoker.invoke() in the implementation to hand over the request to the next filter node.
     *
     * @param invoker    Invoker
     * @param invocation Invocation
     */
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        log.info("try check args filter");
        Object[] objects = invocation.getArguments();
        if (ArrayUtil.isEmpty(objects) || Objects.isNull(objects[0])) {
            return invoker.invoke(invocation);
        }
        Object obj = objects[0];
        if (!ClassUtil.isAssignable(AbstractRequestDTO.class, ClassUtil.getClass(obj))) {
            return invoker.invoke(invocation);
        }
        AbstractRequestDTO requestDTO = (AbstractRequestDTO) obj;
        this.initValidator();
        this.validatorUtil.fastValidate(requestDTO);
        return invoker.invoke(invocation);
    }

    private void initValidator() {
        if (Objects.isNull(this.validatorUtil)) {
            synchronized (this) {
                if (Objects.isNull(this.validatorUtil)) {
                    this.validatorUtil = SpringUtil.getBean(ValidatorUtil.class);
                }
            }
        }
    }
}
